﻿// Server.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include "framework.h"
#include "Server.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// 唯一的应用程序对象

CWinApp theApp;

using namespace std;

int main()
{
    int nRetCode = 0;   

    HMODULE hModule = ::GetModuleHandle(nullptr);

    if (hModule != nullptr)
    {
        // 初始化 MFC 并在失败时显示错误
        if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
        {
            // TODO: 在此处为应用程序的行为编写代码。
            wprintf(L"错误: MFC 初始化失败\n");
            nRetCode = 1;
        }
        else
        {
            // TODO: 在此处为应用程序的行为编写代码。
			
            //显示中文
			setlocale(LC_ALL, "chs");

            //初始化socket
            UINT nPort = 5888;
            WSADATA wsaData;
            WORD wVersionRequested = MAKEWORD(2, 2);
            int err = WSAStartup(wVersionRequested, &wsaData);
            if (err != 0) return 0;

            //判断返回的版本号是否正确
            if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
                WSACleanup();
                return 0;
            }

            //创建一个套接字，用于监听客户端的连接
            SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

            SOCKADDR_IN addrSrv;
            addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
            addrSrv.sin_family = AF_INET;
            addrSrv.sin_port = htons(nPort);//使用端口5888
            bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); //绑定
            listen(sockSrv, 5);

            SOCKADDR_IN addrClient;
            int len = sizeof(SOCKADDR);

            wprintf(L"运行中...\n");

            SOCKET sockConn;
            while (true)
            {
                printf("\n");

                //从连接请求中取出排在最前的一个客户端请求，如果队列为空就阻塞
                //个别时候accet不堵塞，增加一个while模拟堵塞（默认SOCKET_ERROR，等到获取到东西之后/不等有ERROR后退出
                sockConn = SOCKET_ERROR;
                while (sockConn == SOCKET_ERROR)
                {
                    sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
                }

                //## 有客户端连接上来后，做一些处理（此处可以生成一个独立的线程来处理）

                printf("有人来了 - %s:%d\n", inet_ntoa(addrClient.sin_addr), addrClient.sin_port);

                //收消息前告诉客户端已收到（仅此一次机会了）
                char sendBuf[3] = "OK";
                send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);

                //接收客户端信息（没收到就一直等着，直到收到为止）
                char recvBuf[2048];
                recv(sockConn, recvBuf, 2048, 0);
                printf("收到信息：%s\n", recvBuf);

                //关闭和客户端通信的套接字
                closesocket(sockConn);
                printf("走了\n");

                //## END

            }
            //关闭监听套接字
            closesocket(sockSrv);
            //释放套接字库
            WSACleanup();
            
            //让控制台不要消失
            getchar();
        }
    }
    else
    {
        // TODO: 更改错误代码以符合需要
        wprintf(L"错误: GetModuleHandle 失败\n");
        nRetCode = 1;
    }

    return nRetCode;
}
